import { walkUpBindingElementsAndPatterns, WriteFileCallback } from "typescript";

namespace 创造者模式 {
    // 参考:https://blog.csdn.net/qq_34106891/article/details/105655032
    /**
     * 创造者模式, 使用多个简单的对象一步一步构建成一个复杂的对象
     */
    //  构建者模式一般用在构建流程或者组成部件固定的场合，将这些部件分开构建成为组件对象，再将这些组件对象整合成为目标对象。
    // 结构
    // 建造者模式包含如下角色：    
    // Builder：抽象建造者
    // ConcreteBuilder：具体建造者
    // Director：指挥者
    // Product：产品角色

    // 优点:
    /**
     * 客户端（使用程序）不必知道产品内部组成的细节，将产品本身与产品的构建过程解耦，使得相同的创建过程可以创建不同的产品对象
        每一个具体建造者都是相对独立，而与其他的具体建造者无关，因此可以很方便地替换具体建造者或者增加新的具体建造者，用户使用不同的具体建造者即可得到不同的产品对象
        可以更加精细地控制产品的创建过程。
        增加新的具体建造者无须修改原有类库的代码，指挥者类针对抽象建造者编程，系统扩展方便，符合“开闭原则”
     */

    // 缺点
    // 建造者模式所创建的产品一般具有较多的共同点，其组成部分相似， 如果产品之间的差异性很大，则不适合使用建造者模式，因此其使用范围受到一定的限制。
    // 如果产品的内部变化复杂，可能会导致需要定义很多具体建造者类来实现这种变化，导致系统变得很庞大

    // 建造者模式要求按照指定的蓝图建造产品，主要目的是通过组装零配件而产生一个新产品。这就需要生成的产品对象有复杂的内部结构，产品对象具备共性，通过隔离复杂对象的创建和使用，并使得相同的创建过程可以创建不同的产品。

    // 代码实现:

    // 抽象建造者:
    abstract class Builder {
        public abstract builderA(): void;
        public abstract builderB(): void;
        public abstract builderC(): void;
        public abstract builProduct(): Product;
    }

    // 产品角色
    class Product {
        public doSomething(): void {

        }
    }
    // 具体建造者
    class ConcrteBuilder extends Builder {
        private product: Product;
        constructor(product: Product) {
            super();
            this.product = product;
        }

        public builderA(): void { }
        public builderB(): void {

        }
        public builderC(): void {

        }

        // 最终组建一个产品
        public builProduct(): Product {
            return this.product;
        }
    }

    // 指挥者
    class Director {
        private _builder: Builder;
        constructor(builder: Builder) {
            this._builder = builder;
        }

        setBuilder(builder: Builder) {
            this._builder = builder;
        }

        // 将处理建造的流程交给指挥者
        public constructorProduct() {
            this._builder.builderA();
            this._builder.builderB();
            this._builder.builderC();
            return this._builder.builProduct();
        }
    }

    // 具体使用
    // ①先创建一个具体建造起
    const builder: Builder = new ConcrteBuilder(new Product());
    // ②生成一个指挥官
    const director: Director = new Director(builder);
    // ③指挥官创建根据特定流程创建产品
    const product: Product = director.constructorProduct();

    console.log("product---", product);




}